<template>
  <div class="md-playground-wrapper">
    <div class="md-playground">
      <header class="page-header">
        <div>
          <h1>Markdown 解析对比实验</h1>
          <p>在这里输入任意 Markdown 文本，使用 3 个解析库对比渲染效果。</p>
        </div>
      </header>

      <section class="input-section">
        <label class="input-label" for="md-input">Markdown 输入</label>
        <textarea
          id="md-input"
          v-model="input"
          class="md-input"
          placeholder="在这里输入或粘贴 Markdown 文本，例如：&#10;&#10;### 标题&#10;- 列表项 1&#10;- 列表项 2&#10;&#10;**加粗文本** 和 `行内代码`"
        ></textarea>
        <div class="input-actions">
          <el-button type="primary" @click="handleParse">解析转换</el-button>
          <el-button @click="resetToSample">加载示例数据</el-button>
        </div>
      </section>

      <section v-if="parsed" class="result-section">
        <div class="result-grid">
          <article class="render-card">
            <header class="render-header primary">
              <span class="title">markdown-it 渲染结果</span>
            </header>
            <div class="render-body" v-html="htmlMarkdownIt"></div>
          </article>

          <article class="render-card">
            <header class="render-header alt-one">
              <span class="title">Showdown 渲染结果</span>
            </header>
            <div class="render-body" v-html="htmlShowdown"></div>
          </article>

          <article class="render-card">
            <header class="render-header alt-two">
              <span class="title">remark 渲染结果</span>
            </header>
            <div class="render-body" v-html="htmlRemark"></div>
          </article>
        </div>
      </section>

      <el-empty
        v-else
        description="请输入 Markdown 文本后点击“解析转换”查看效果"
        class="empty-state"
      />
    </div>
  </div>
</template>

<script setup>
import { ref } from "vue";
import MarkdownIt from "markdown-it";
import showdown from "showdown";
import { remark } from "remark";
import remarkHtml from "remark-html";

const input = ref("");
const parsed = ref(false);

const htmlMarkdownIt = ref("");
const htmlShowdown = ref("");
const htmlRemark = ref("");

// 与测试页保持一致的 markdown-it 配置
const mdParser = new MarkdownIt({
  html: true,
  linkify: true,
  breaks: true,
});

// Showdown 配置
const showdownConverter = new showdown.Converter({
  noHeaderId: true,
  smartIndentationFix: true,
  simplifiedAutoLink: false,
  openLinksInNewWindow: false,
  strikethrough: true,
  literalMidWordUnderscores: true,
  tables: true,
  simpleLineBreaks: false,
});

// remark 管线
const remarkProcessor = remark().use(remarkHtml, { sanitize: false });

// 尽量兼容 test.md 中 content 的字符串形式（包含字面量 \n 等）
const normalizeInput = (text = "") =>
  text
    .replace(/\r\n/g, "\n")
    .replace(/\r/g, "\n")
    // 将字符串中的字面量 \n 转为真实换行
    .replace(/\\n/g, "\n")
    // 粗体语法后多余空格修正：** xx -> **xx
    .replace(/\*\*\s+/g, "**")
    .replace(/__\s+/g, "__")
    // 列表项前两个以上空格归一为一个空格：-  xx -> - xx
    .replace(/(^|\n)(-\s{2,})/g, (_, prefix) => `${prefix}- `);

const handleParse = () => {
  const normalized = normalizeInput(input.value || "");
  const source = normalized.trim();
  if (!source) {
    parsed.value = false;
    htmlMarkdownIt.value = "";
    htmlShowdown.value = "";
    htmlRemark.value = "";
    return;
  }

  try {
    htmlMarkdownIt.value = mdParser.render(source);
  } catch (e) {
    console.error("markdown-it 解析失败", e);
    htmlMarkdownIt.value = source;
  }

  try {
    htmlShowdown.value = showdownConverter.makeHtml(source);
  } catch (e) {
    console.error("showdown 解析失败", e);
    htmlShowdown.value = source;
  }

  try {
    const file = remarkProcessor.processSync(source);
    htmlRemark.value = String(file.value || "");
  } catch (e) {
    console.error("remark 解析失败", e);
    htmlRemark.value = source;
  }

  parsed.value = true;
};

const sampleText = `以下是一个包含多种 Markdown 语法的示例，用于对比不同解析库的渲染差异：

---

### **1. 标题与分隔线测试**

#### **1.1 子标题**

- 列表项 1
- 列表项 2
  - 子项 A
  - 子项 B

**加粗文本**、_斜体文本_、~~删除线~~ 和 \`行内代码\`

---

### **2. 特殊格式与不太标准写法**

需求处理**

#### **5.1 数据存储架构**\\n-  **分布式文件系统**：采用快照文件系统实现分布式存储。

- ** бю Netherlands的未来教育政策**：混合语言与特殊字符。

> 引用块测试：这是一段引用文字。

1. 有序列表 1
2. 有序列表 2

\`\`\`python
def hello():
    print("code block 测试")
\`\`\`
`;

const resetToSample = () => {
  input.value = sampleText;
  handleParse();
};
</script>

<style scoped>
.md-playground-wrapper {
  width: 100%;
  height: 100vh;
  overflow-y: auto;
  background: #f4f6fb;
  padding: 16px 0 32px;
}

.md-playground {
  max-width: 1400px;
  margin: 0 auto;
  padding: 22px 28px 28px;
  background: #ffffff;
  border-radius: 16px;
  box-shadow: 0 20px 40px rgba(15, 23, 42, 0.12);
}

.page-header {
  border-radius: 12px;
  padding: 18px 20px;
  background: linear-gradient(135deg, #2563eb 0%, #4f46e5 100%);
  color: #ffffff;
  margin-bottom: 24px;
}

.page-header h1 {
  margin: 0 0 8px;
  font-size: 22px;
}

.page-header p {
  margin: 0;
  font-size: 14px;
  opacity: 0.92;
}

.input-section {
  margin-bottom: 24px;
}

.input-label {
  display: block;
  margin-bottom: 8px;
  font-size: 14px;
  font-weight: 600;
  color: #374151;
}

.md-input {
  width: 100%;
  min-height: 160px;
  max-height: 260px;
  padding: 12px 14px;
  border-radius: 10px;
  border: 1px solid #d1d5db;
  resize: vertical;
  font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas,
    "Liberation Mono", "Courier New", monospace;
  font-size: 13px;
  line-height: 1.6;
  outline: none;
  transition: border-color 0.2s ease, box-shadow 0.2s ease;
  background: #f9fafb;
}

.md-input:focus {
  border-color: #2563eb;
  box-shadow: 0 0 0 1px rgba(37, 99, 235, 0.4);
  background: #ffffff;
}

.input-actions {
  margin-top: 10px;
  display: flex;
  gap: 10px;
}

.result-section {
  margin-top: 8px;
}

.result-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 16px;
}

.render-card {
  background: #f9fafb;
  border-radius: 12px;
  border: 1px solid #e5e7eb;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.render-header {
  padding: 8px 12px;
  font-size: 13px;
  font-weight: 600;
  color: #4b5563;
  background: rgba(148, 163, 184, 0.14);
}

.render-header.primary {
  color: #1d4ed8;
  background: rgba(59, 130, 246, 0.15);
}

.render-header.alt-one {
  color: #92400e;
  background: rgba(251, 191, 36, 0.16);
}

.render-header.alt-two {
  color: #065f46;
  background: rgba(16, 185, 129, 0.14);
}

.render-body {
  padding: 12px 14px;
  font-size: 14px;
  line-height: 1.7;
  color: #374151;
  max-height: 440px;
  overflow: auto;
}

.render-body :deep(h1),
.render-body :deep(h2),
.render-body :deep(h3),
.render-body :deep(h4) {
  margin: 16px 0 8px;
  color: #111827;
}

.render-body :deep(p) {
  margin: 8px 0;
}

.render-body :deep(ul),
.render-body :deep(ol) {
  margin: 8px 0 8px 20px;
}

.render-body :deep(code) {
  background: rgba(37, 99, 235, 0.08);
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 13px;
}

.render-body :deep(pre) {
  background: #0f172a;
  color: #f9fafb;
  padding: 12px;
  border-radius: 8px;
  overflow-x: auto;
}

.render-body :deep(.image-placeholder) {
  margin: 12px 0;
  padding: 10px 12px;
  border-radius: 8px;
  background: rgba(59, 130, 246, 0.08);
  color: #1d4ed8;
  font-size: 14px;
  font-style: italic;
}

.empty-state {
  margin-top: 40px;
}

@media (max-width: 992px) {
  .result-grid {
    grid-template-columns: repeat(2, minmax(0, 1fr));
  }
}

@media (max-width: 768px) {
  .md-playground-wrapper {
    padding: 12px 0 28px;
  }

  .md-playground {
    padding: 16px;
    border-radius: 0;
    box-shadow: none;
  }

  .result-grid {
    grid-template-columns: 1fr;
  }
}
</style>
